#include "../src/IPCClient.hpp"
#include "../src/MQTT.hpp"
#include <yaml-cpp/yaml.h>
#include <filesystem>
#include <format>
#include <unistd.h>
#include <spdlog/spdlog.h>

MQTT mqtt;
IPCClient ipc;

static const char* configFile="/etc/supermatrix/DeviceNetwork.yaml";

MQTT::ConnectInf LoadConfig()
{
  if(!std::filesystem::exists(configFile))
    throw std::logic_error("Can't open config file : DeviceNetwork.yaml");
  
  YAML::Node config=YAML::LoadFile(configFile);
  if(!config["MQTT"] || config["MQTT"].Type()!=YAML::NodeType::Map)
    throw std::runtime_error("Config file tag [MQTT] Can't found");
  YAML::Node MQTTData=config["MQTT"].as<YAML::Node>();
  MQTT::ConnectInf inf;
  inf.clientID=MQTTData["clientid"].as<std::string>();
  inf.username=MQTTData["username"].as<std::string>();
  inf.password=MQTTData["password"].as<std::string>();
  inf.ipaddr=MQTTData["server"].as<std::string>();
  inf.port=MQTTData["port"].as<long>();
  return inf;
}

int main()
{
  spdlog::info(">>>>>> DeviceNetwork Booting");
  mqtt.funcAllStartShot=[](){
    bool errflag=false;
    std::stringstream errmsg;
    for(const std::string & i : ipc.GetAllDevices())
    {
      try
      {
        ipc.StartShot(i);
      }
      catch(const std::exception& e)
      {
        errflag=true;
        errmsg<<i<<',';
      }
    }
    if(errflag)
      throw std::runtime_error(std::format("Exec funcAllStartShot Failed, Device: {}",errmsg.str()));
  };
  mqtt.funcAllStopShot=[](){
    bool errflag=false;
    std::stringstream errmsg;
    for(const std::string & i : ipc.GetAllDevices())
    {
      try
      {
        ipc.StopShot(i);
      }
      catch(const std::exception& e)
      {
        errflag=true;
        errmsg<<i<<',';
      }
    }
    if(errflag)
      throw std::runtime_error(std::format("Exec funcAllStopShot Failed, Device: {}",errmsg.str()));
  };
  mqtt.funcAllShotStatus=[]()->bool{
    bool errflag=false;
    std::stringstream errmsg;
    bool checkstatus=true;
    bool first=true;
    for(const std::string& i : ipc.GetAllDevices())
    {
      try
      {
        if(first) [[unlikely]]
        {
          checkstatus=ipc.ShotStatus(i);
          first=false;
        }
        else if(checkstatus!=ipc.ShotStatus(i)) [[likely]]
        {
          errflag=true;
          errmsg<<i<<"[Status], ";
        }
      }
      catch(const std::exception& e)
      {
          errflag=true;
          errmsg<<i<<',';
      }
    }
    if(errflag)
      throw std::runtime_error(std::format("Exec funcAllShotStatus Failed, Device: {}",errmsg.str()));
    return checkstatus;
  };
  
  ipc.Boot();
  mqtt.Boot(LoadConfig());
  spdlog::info(">>>>>> DeviceNetwork Readying");
  while(sleep(10)==0) ;
  spdlog::info("<<<<<< DeviceNetwork Exiting");
  return 0;
}
